
package com.x52im.rbchat.logic.sns_group;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.eva.android.ArrayListObservable;
import com.eva.android.widget.DataLoadableActivity;
import com.eva.android.widget.AListAdapter2;
import com.eva.android.widget.DataLoadingAsyncTask;
import com.eva.android.widget.WidgetUtils;
import com.eva.android.widget.alert.AlertDialog;
import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.dto.DataFromServer;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.R;
import com.x52im.rbchat.cache.ImageCacheLoader;
import com.x52im.rbchat.network.http.HttpRestHelper;
import com.x52im.rbchat.network.http.async.QueryFriendInfo;
import com.x52im.rainbowchat.http.logic.dto.GroupEntity;
import com.x52im.rainbowchat.http.logic.dto.GroupMemberEntity;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rbchat.cache.GroupsProvider;
import com.x52im.rbchat.logic.chat_group.utils.GChatDataHelper;
import com.x52im.rbchat.utils.IntentFactory;

import java.util.ArrayList;

/**
 * 群成员操作界面。
 *
 * @author Tony ma
 * @since 4.3
 */
public class GroupMemberActivity extends DataLoadableActivity
{
    private final static String TAG = GroupMemberActivity.class.getSimpleName();

    /** 本界面用途之：创建群 */
    public final static int USED_FOR_CREATE_GROUP = 0;
    /** 本界面用途之：查看群成员(普通群员可用)或管理群成员(群主可用，群主有删除功能) */
    public final static int USED_FOR_VIEW_OR_MANAGER_MEMBERS = 1;
    /** 本界面用途之：邀请入群 */
    public final static int USED_FOR_INVITE_MEMBERS = 2;
    /** 本界面用途之：转让群 */
    public final static int USED_FOR_TRANSFER = 3;

    /** 【内容UI主组件1】：群列表 */
    private ListView groupListView;
    /** 群列表Adapter */
    private GroupMemberListAdapter groupListAdapter;

    /** 【内容UI主组件2】：父布局 - 添加好友的父组件引用 */
    private ViewGroup addGroupLL = null;
    /** 按钮：确认 */
    private Button btnOK = null;
//    /** 按钮：取消 */
//    private Button btnCancel = null;

    /** 群列表的数据结构对象. */
    private ArrayList<GroupMemberEntity> staticListData = null;

    /** Intent传进来的参数：本界面的用途 */
    private int usedForForInit = -1;
    /** Intent传进来的参数：本参数在 {@link #usedForForInit}==USED_FOR_CREATE_GROUP 时无意义 */
    private String gidForInit = null;
    /** Intent传进来的参数：打开本界面的是否是本群群主 */
    private boolean isGroupOwnerForInit = false;
    /** Intent传进来的参数：表示默认选中的uid，本参数当前主要用于{@link #usedForForInit}==USED_FOR_CREATE_GROUP 时 */
    private String defaultSelectedUidForInit = null;

    // 是否显示选择框
    private boolean showCheckBox = true;
    // 是否支持单选
    private boolean singleSelection = false;

    /**
     * {@inheritDoc}
     */
    @Override
    protected void initDataFromIntent()
    {
        //解析从intent中传过来的数据
        ArrayList intentDatas = IntentFactory.parseGroupMemberActivityIntent(getIntent());

        usedForForInit = (Integer) intentDatas.get(0);
        gidForInit = (String)intentDatas.get(1);
        isGroupOwnerForInit = (Boolean)intentDatas.get(2);
        defaultSelectedUidForInit = (String)intentDatas.get(3);

        Log.w(TAG, "【群成员查看】Intent传进来的参数：usedForForInit="
                +usedForForInit+", gidForInit="+gidForInit+", isGroupOwnerForInit="+isGroupOwnerForInit);
    }

    // 界面恢复到前台时
    protected void onResume()
    {
        super.onResume();

        // 强制要求每次进来都更新列表（从而保证当数据更新后能及时刷新最新的显示）
        groupListAdapter.notifyDataSetChanged();
    }

    @Override
    protected void initViews(Bundle savedInstanceState)
    {
        //设定自定义标题栏（设定此值即意味着开启自定义标题栏的使用，必须要在setContentView前设定）
        customeTitleBarResId = R.id.groupchat_groupmember_list_view_titleBar;
        //养成良好习惯：首先设置主layout，确保后绪的操作中使用到的组件都可以被find到
        setContentView(R.layout.groupchat_groupmember_list);

        // 各UI组件
        addGroupLL = (ViewGroup)findViewById(R.id.groupchat_groupmember_list_view_addGroupLL);
        // 标题栏按钮实例
        btnOK = this.getCustomeTitleBar().getRightGeneralButton();
        // 设置字体大小
        btnOK.setTextSize(TypedValue.COMPLEX_UNIT_SP,12); // 12sp
        // 设置标题栏按钮的ui样式
        setTextButtonStyleForTitle(this, btnOK);
        // 设置ok按钮的初始状态
        _setOkButtonEnable(false);

        // 列表及列表的adapter
        groupListView = (ListView) findViewById(R.id.groupchat_groupmember_list_listView);
        // 生成适配器的ImageItem <====> 动态数组的元素，两者一一对应
        if(staticListData == null)//先实例化列表的全局数据结构对对象（如果已经实例化了就不需要现新那对 象了，目的是为了保留上次的数据）
            staticListData = new ArrayList<GroupMemberEntity>();
        groupListAdapter = new GroupMemberListAdapter(this);
        groupListView.setAdapter(groupListAdapter);

        if(usedForForInit == USED_FOR_CREATE_GROUP)
        {
            this.setTitle("创建群聊");
            this.btnOK.setVisibility(View.VISIBLE);
            this.showCheckBox = true;
        }
        else if(usedForForInit == USED_FOR_VIEW_OR_MANAGER_MEMBERS)
        {
            // 普通群员（只能查看群聊成员）
            if(!isGroupOwnerForInit)
            {
                this.setTitle("查看群员");
                this.btnOK.setVisibility(View.GONE);
                this.showCheckBox = false;
            }
            // 群主（可以删除群员）
            else
            {
                this.setTitle("管理群员");
                this.btnOK.setVisibility(View.VISIBLE);
                this.showCheckBox = true;
            }
        }
        else if(usedForForInit == USED_FOR_INVITE_MEMBERS)
        {
            this.setTitle("邀请入群");
        }
        else if(usedForForInit == USED_FOR_TRANSFER)
        {
            this.setTitle("选择新群主");
            singleSelection = true;
        }
    }

    /**
     * 本方法由父类的onCreate()调用，子类可在此方法中为各UI功能组件增加事件临听。
     */
    @Override
    protected void initListeners() {
        // 确认按钮事件处理
        btnOK.setOnClickListener(v -> {
            // 创建群
            if (usedForForInit == USED_FOR_CREATE_GROUP) {
                if (getSelectedItems().size() > 0) {
                    // 向服务端提交建群请求
                    new SubmitCreateGroupAsyncTask().execute();
                } else {
                    WidgetUtils.showToast(GroupMemberActivity.this, "请选择要加入群聊的好友！", WidgetUtils.ToastType.WARN);
                }
            }
            // 管理/删除群成员（此功能只有群主才有）
            else if (usedForForInit == USED_FOR_VIEW_OR_MANAGER_MEMBERS) {
                // 群主才能提交
                if (isGroupOwnerForInit) {
                    ArrayList<ArrayList> willBeDelete = getSelectedItemsSimple();
                    if (willBeDelete != null && willBeDelete.size() > 0) {
                        new OperationsAsyncTask().execute(USED_FOR_VIEW_OR_MANAGER_MEMBERS, willBeDelete);
                    }
                }
            }
            // 邀请入群
            else if (usedForForInit == USED_FOR_INVITE_MEMBERS) {
                new OperationsAsyncTask().execute(USED_FOR_INVITE_MEMBERS, getSelectedItemsSimple());
            }
            // 转让群
            else if (usedForForInit == USED_FOR_TRANSFER) {
                new OperationsAsyncTask().execute(USED_FOR_TRANSFER);
            }
        });
    }

    /**
     * 获得单选模式下被选中的用户.
     *
     * @return
     */
    private GroupMemberEntity getSingleSelectedUser() {
        GroupMemberEntity retGme = null;
        for (GroupMemberEntity gme : this.groupListAdapter.getListData()) {
            if (gme.isSelected()) {
                retGme = gme;
                break;
            }
        }
        return retGme;
    }

    /**
     * 获得选中的行（只包含简单的列，主要用于提交到服务端，不必要的字段就没有必要一起发过去浪费流量）。
     * <b>注意：</b>本方法返回的集合，通常用于提交到服务端的http接口，因而要与对应的接口要求字段保持一致哦！！！
     *
     * @return
     */
    private ArrayList<ArrayList> getSelectedItemsSimple() {
        ArrayList<ArrayList> items = new ArrayList<>();
        for (GroupMemberEntity gme : this.groupListAdapter.getListData()) {
            if (gme.isSelected()) {
                // 以下字段及顺序请确保与http服务端的接口保持一致！
                ArrayList<String> row = new ArrayList<>();
                row.add(gme.getG_id());
                row.add(gme.getUser_uid());
                row.add(gme.getNickname());
                items.add(row);
            }
        }
        return items;
    }

    /**
     * 获得当前选中的行。
     *
     * @return
     */
    private ArrayList<GroupMemberEntity> getSelectedItems() {
        ArrayList<GroupMemberEntity> items = new ArrayList<GroupMemberEntity>();
        for (GroupMemberEntity gme : this.groupListAdapter.getListData()) {
            if (gme.isSelected()) {
                items.add(gme);
            }
        }
        return items;
    }

    /**
     * 返回选中的行数。
     *
     * @return
     */
    public int getSelectedCount() {
        int cnt = 0;
        for(GroupMemberEntity gme : this.groupListAdapter.getListData()) {
            if(gme.isSelected()) {
                cnt += 1;
            }
        }
        return cnt;
    }

    /**
     * 重置确认为初始状态：不可点击、文字内容显示为"确定"、以及按钮的UI样式为半透明效果。
     */
    private void _resetOkButton() {
        // 设置标题栏保存按钮的可用与禁用时样式
        setTextButtonEnableForTitle(this, this.btnOK, false);
        // 群主使用查看群员功能时，确认按钮显示为删除
        if (usedForForInit == USED_FOR_VIEW_OR_MANAGER_MEMBERS && isGroupOwnerForInit)
            this.btnOK.setText("删除");
        else
            this.btnOK.setText("确定");
    }

    /**
     * 决置确认按钮的可用性。
     *
     * @param enabled
     */
    private void _setOkButtonEnable(boolean enabled) {
        if (enabled) {
            // 设置标题栏保存按钮的可用与禁用时样式
            setTextButtonEnableForTitle(this, this.btnOK, true);
        } else {
            _resetOkButton();
        }
    }

    /**
     * 设置确认按钮上的选中数量，并根据选中数据量决定按钮是否可点击。
     *
     * @param selectedCount
     */
    private void setOkButtonForSelected(int selectedCount) {
        if (selectedCount > 0) {
            _setOkButtonEnable(true);
            // 群主使用查看群员功能时，确认按钮显示为删除
            if (usedForForInit == USED_FOR_VIEW_OR_MANAGER_MEMBERS && isGroupOwnerForInit)
                this.btnOK.setText("删除(" + selectedCount + ")");
            else if (usedForForInit == USED_FOR_TRANSFER)
                this.btnOK.setText("确定");
            else
                this.btnOK.setText("确定(" + selectedCount + ")");
        } else {
            _setOkButtonEnable(false);
        }
    }

    /**
     * 本方法默认被父类的loadData调用，用于异步刷新界面数据.
     *
     * @param params loadData中传进来的参数，本类中该参数没有被用到
     */
    @Override
    protected DataFromServer queryData(String... params) {
        DataFromServer dfs = new DataFromServer();

        // 准备创建群数据（直接取我的本地好友列表即可）
        if (usedForForInit == USED_FOR_CREATE_GROUP) {
            dfs.setSuccess(true);

            ArrayList<GroupMemberEntity> memberList = new ArrayList<GroupMemberEntity>();
            // 我的好友列表数据
            ArrayListObservable<RosterElementEntity> myRoster = imc().getFriendsListProvider().getRosterData(this, false);
            if (myRoster != null && myRoster.getDataList().size() > 0) {
                for (RosterElementEntity ree : myRoster.getDataList()) {
                    GroupMemberEntity m = constructFromRosterElement(ree);
                    if (m != null) {
                        // 设置默认选中的uid，且不允许编辑，当前用于从"聊天信息"界面中的"+"号图标点进来创建群时
                        if (defaultSelectedUidForInit != null && defaultSelectedUidForInit.equals(m.getUser_uid())) {
                            m.setSelected(true);
                            m.setEditable(false);
                        }
                        // 加入集合
                        memberList.add(m);
                    }
                }
            }

            // 将组织好的数据放入DataFromServer对象，refreshToView(..)方法中将能直接拿到
            dfs.setReturnValue(memberList);
        }
        // 准备查看群成员数据（如果是群主的话，是可以删除群成员的）
        else if (usedForForInit == USED_FOR_VIEW_OR_MANAGER_MEMBERS) {
            // 直接从服务器查询群成员列表
            dfs = HttpRestHelper.submitGetGroupMembersListFromServer(gidForInit);
        }
        // 准备邀请入群数据
        else if (usedForForInit == USED_FOR_INVITE_MEMBERS) {
            // 先从服务端查询群成员列表
            dfs = HttpRestHelper.submitGetGroupMembersListFromServer(gidForInit);
        }
        // 准备转让群数据
        else if (usedForForInit == USED_FOR_TRANSFER) {
            // 先从服务端查询群成员列表
            dfs = HttpRestHelper.submitGetGroupMembersListFromServer(gidForInit);
        }

        return dfs;
    }

    /**
     * 本方法的作用是把queryData里返回的数据放到UI上显示.
     */
    @Override
    protected void refreshToView(Object dataToView) {
        // 显示创建群数据（选择好友并创建）
        if (usedForForInit == USED_FOR_CREATE_GROUP) {
            staticListData = (ArrayList<GroupMemberEntity>) dataToView;
        }
        // 显示查看群成员数据
        else if (usedForForInit == USED_FOR_VIEW_OR_MANAGER_MEMBERS) {
            if (dataToView != null) {
                staticListData = HttpRestHelper.parseGetGroupMembersListFromServer((String) dataToView);
            }
        }
        // 显示邀请入群数据（可以被邀请的人条件是：“是我的好友” && “还没加入该群”）
        else if (usedForForInit == USED_FOR_INVITE_MEMBERS) {
            // 可以被邀请的好友
            ArrayList<GroupMemberEntity> willBeInvite = new ArrayList<>();

            if (dataToView != null) {
                // 从服务器读取到的当前群成员列表
                ArrayList<GroupMemberEntity> currentGroupMembers = HttpRestHelper.parseGetGroupMembersListFromServer((String) dataToView);

                // 我的当前所有好友列表数据
                ArrayListObservable<RosterElementEntity> myRoster = MyApplication.getInstance(this).getIMClientManager().getFriendsListProvider().getRosterData(this, false);

                // 遍历我的好友列表，如果该好友不当前群成员列表里，就表示可以被邀请入群
                // 代码逻辑：以下代码就是为了将我的好友列表中去掉已经加入了此群的人，余下的人就是本次可以被邀请进入本群的人了
                for (RosterElementEntity friend : myRoster.getDataList()) {
                    // 看该好友是否已经存在成员列表里
                    for (int i = 0; i < currentGroupMembers.size(); i++) {
                        GroupMemberEntity member = currentGroupMembers.get(i);

                        // 是否已在存在？
                        boolean isMatched = friend.getUser_uid().equals(member.getUser_uid());
                        // 已经存在（直接跳出本次的成员列表匹配循环，接着开始上一层循环——即看下一个好友是否在列表里）
                        if (isMatched) {
                            Log.i(TAG, "[i=" + i + "]A正在匹配friend.getUser_uid()=" + friend.getUser_uid() + "，member.getUser_uid()=" + member.getUser_uid() + "， 匹配了吗？" + isMatched);
                            break;
                        }
                        // 还不存在列表里
                        else {
                            Log.i(TAG, "[i=" + i + "]B正在匹配friend.getUser_uid()=" + friend.getUser_uid() + "，member.getUser_uid()=" + member.getUser_uid() + "， 匹配了吗？" + isMatched);
                            // 已经查找到了成员列表的最后一个还没有匹配上：那这个好友肯定就不在成员列表里（就是我们要找的）
                            if (i == currentGroupMembers.size() - 1) {
                                // 将此好友加入我的可以被邀请数据集合中
                                GroupMemberEntity m = constructFromRosterElement(friend);
                                if (m != null)
                                    willBeInvite.add(m);
                            }
                        }
                    }
                }
            }

            staticListData = willBeInvite;
        }
        // 转让群（群主可以转让给本群内除已之外的其他人）
        else if (usedForForInit == USED_FOR_TRANSFER) {
            RosterElementEntity localUserInfo = MyApplication.getInstance(GroupMemberActivity.this).getIMClientManager().getLocalUserInfo();
            if (localUserInfo != null) {
                // 本群所有成员（包括我自已）
                ArrayList<GroupMemberEntity> groupMembers = HttpRestHelper.parseGetGroupMembersListFromServer((String) dataToView);
                if (groupMembers.size() > 0) {
                    // 以下代码用来找到"我"在群成员列表中的索引
                    int indexOfMe = -1;
                    for (int i = 0; i < groupMembers.size(); i++) {
                        String localUid = localUserInfo.getUser_uid();
                        String groupMembersUid = groupMembers.get(i).getUser_uid();
                        if (localUid.equals(groupMembersUid)) {
                            indexOfMe = i;
                            break;
                        }
                    }

                    // 将"我"从群成员列表数据集合中删除
                    if (indexOfMe != -1)
                        groupMembers.remove(indexOfMe);

                    staticListData = groupMembers;
                }
            }
        }

        // 设置列表数据
        groupListAdapter.setListData(staticListData);
        //更新Ui
        groupListAdapter.notifyDataSetChanged();
    }

    private GroupMemberEntity constructFromRosterElement(RosterElementEntity ree) {
        if (ree != null) {
            GroupMemberEntity m = new GroupMemberEntity();
            m.setG_id(gidForInit);
            m.setUser_uid(ree.getUser_uid());
            m.setNickname(ree.getNickname());
            m.setSelected(false);
            m.setUserAvatarFileName(ree.getUserAvatarFileName());
            return m;
        }
        return null;
    }

    /**
     * 设置标题栏文本按钮的显示样式。
     */
    public static void setTextButtonStyleForTitle(Context c, Button btn){
        if(btn == null)
            return;

        // 标题栏右边的按钮
        btn.setVisibility(View.VISIBLE);
        // 设置按钮衬距
        WidgetUtils.setMargins(btn, 0, 0, WidgetUtils.dip2px(c, 15.0f), 0);
        // 设置按钮高度
        WidgetUtils.setHeight(btn, WidgetUtils.dip2px(c, 32.0f));
    }

    /**
     * 设置标题栏文本按钮的可用与禁用时样式。
     */
    public static void setTextButtonEnableForTitle(Context c, Button btn, boolean enabled) {
        if (btn == null)
            return;

        if (enabled) {
            btn.setBackgroundResource(R.drawable.common_btn_red_2018);
            btn.setTextColor(c.getResources().getColor(R.color.white));
            btn.setEnabled(true);
        } else {
            btn.setBackgroundResource(R.drawable.common_btn_red_2018_transparent);
            btn.setTextColor(c.getResources().getColor(R.color.white_50transparent));
            btn.setEnabled(false);
        }
    }


    //-------------------------------------------------------------------------------- 内部类

    /**
     * 列表的adapter类实现.
     */
    private class GroupMemberListAdapter extends AListAdapter2<GroupMemberEntity>
    {
        public GroupMemberListAdapter(Activity context)
        {
            super(context, R.layout.groupchat_groupmember_list_item);
        }

        // 重写本方法，以便使用自定义的列表数据模型
        @Override
        protected ArrayList<GroupMemberEntity> createListData()
        {
            // 注意：不能使用与AListAdapter里默认的数据模型listData一样的名字哦，否则将错误地引用父类该对象从而导致空指针
            return staticListData;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent)
        {
            //列表item上的：
            ViewGroup layoutOfGotochat = null;
            TextView viewName = null;
            TextView viewId = null;
            CheckBox cbSelect = null;
            ImageView viewAvatar = null;
            TextView viewOwnerFlag = null;
            TextView viewMyselfFlag = null;


            //----------------------------------------------------------------------------- （1）UI初始化
            //当的item布局实例已经存在（不在存，意味着这个item刚好从不可见区移到可见区时）
            boolean needCreateItem = (convertView == null);
            //正在操作的列表行的数据集
            final GroupMemberEntity rowData = listData.get(position);
            if (needCreateItem)
                //明细item的UI实例化
                convertView = layoutInflater.inflate(itemResId, null);
            //item里的操作组件实例
            layoutOfGotochat = (ViewGroup) convertView.findViewById(R.id.groupchat_groupmember_list_item_contentLL);
            viewName = (TextView) convertView.findViewById(R.id.groupchat_groupmember_list_item_nameView);
            viewId = (TextView) convertView.findViewById(R.id.groupchat_groupmember_list_item_idView);
            cbSelect = (CheckBox) convertView.findViewById(R.id.groupchat_groupmember_list_item_selectCb);
            viewAvatar = (ImageView) convertView.findViewById(R.id.groupchat_groupmember_list_item_imageView);
            viewOwnerFlag = (TextView) convertView.findViewById(R.id.groupchat_groupmember_list_item_ownerFlagView);
            viewMyselfFlag = (TextView) convertView.findViewById(R.id.groupchat_groupmember_list_item_myselfFlagView);

            // 是否显示选择框
            if(showCheckBox) {
                // 在删除群员的模下，群主不能删除自已！
                if(isGroupOwnerCanNotDeleteHimself(rowData))
                    cbSelect.setVisibility(View.GONE);
                else
                    cbSelect.setVisibility(View.VISIBLE);
            }
            else {
                cbSelect.setVisibility(View.GONE);
            }
            // 设置是否可编辑
            cbSelect.setEnabled(rowData.isEditable());

            // 如果当前行是群主，则显示群主标签
            GroupEntity ge = MyApplication.getInstance(context).getIMClientManager().getGroupsProvider().getGroupInfoByGid(gidForInit);
            if(ge != null && rowData.getUser_uid().equals(ge.getG_owner_user_uid()))
                viewOwnerFlag.setVisibility(View.VISIBLE);
            else
                viewOwnerFlag.setVisibility(View.GONE);

            // 如果是“我”则显示“我”标签
            viewMyselfFlag.setVisibility(isMyself(rowData)?View.VISIBLE:View.GONE);


            //----------------------------------------------------------------------------- （2）增加事件处理器
            //各操作组件的事件监听器只需要在convertView被实例化时才需要重建（convertView需要被实例化
            //当然就意味着它上面的所有操作组件都已经重新新建了）
            //** 关于事件处理器的说明：事件处理器的增加其实可以不这么麻烦，直接每getView一次就给组件new一个处理器，
            //** 这样做的好处是简单，但显然存在资源浪费（每刷新一次view就新建监听器）。而现在的实现就跟Android的列表
            //** 实现原理一样，在切换到下一组item前，监听器永远只有一屏item的数量（刷新时只需要即时刷新对应item的数据到
            //** 它的监听器里），这样就节省了资源开销！
            if (needCreateItem)
            {
                // 显示选择框时，点击内容区的事件响应
                if(showCheckBox)
                {
                    // 点击进入聊天事件处理
                    ContentOnClickListener playLIstener = new ContentOnClickListener();
                    layoutOfGotochat.setOnClickListener(playLIstener);
                    layoutOfGotochat.setTag(playLIstener);
                }
                else
                {
                    // 点击查看用户信息的事件处理
                    HeadIconOnClickListener headLIstener = new HeadIconOnClickListener();
                    layoutOfGotochat.setOnClickListener(headLIstener);
                    layoutOfGotochat.setTag(headLIstener);
                }

                // 点击头像查看用户信息的事件处理
                HeadIconOnClickListener headLIstener = new HeadIconOnClickListener();
                viewAvatar.setOnClickListener(headLIstener);
                viewAvatar.setTag(headLIstener);
            }


            //----------------------------------------------------------------------------- （3）
            //给标签设置值，以供用户查看
            viewName.setText(GroupsProvider.getNickNameInGroup(rowData.getNickname(), rowData.getNickname_ingroup()));
            viewId.setText("ID："+rowData.getUser_uid());
            cbSelect.setChecked(rowData.isSelected());


            //----------------------------------------------------------------------------- 异步加载头像

            // 根据Glide官方指南的说明：https://muyangmin.github.io/glide-docs-cn/doc/getting-started.html#%E5%9C%A8-listview-%E5%92%8C-recyclerview-%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8
            // 由于RecycleView中view的复用问题，为了防止图片显示错乱，如果它在之前的位置上用 Glide 进行过加载操作，那么在新的位置上要去执行一个新的加载操作或调用 clear()，
            // 实测通过clear()或通过Glide.with(context).load(默认占位图的资源id)两种方式都可以解决错乱问题，但clear更好，因为它不会在发生图片显示时闪烁一下的问题
//          Glide.with(context).load(R.drawable.main_alarms_sns_addfriendreject2r_message_icon).into(holder.viewIcon); // 解决方法1
            Glide.with(context).clear(viewAvatar);// 解决方法2
            // clear完成后设置默认占位图，确保图片显示不出现Glide导致的错位问题
            viewAvatar.setImageResource(R.drawable.default_avatar_yuan_50_3x);

            // userAvatarFileName中存放的中该人员的头像存放于服务端的文件名（也将原样用于本地的缓存文件名）为null即表示该人员没有头像
            if(!CommonUtils.isStringEmpty(rowData.getUserAvatarFileName(), true))
            {
                // 加载头像图片
                ImageCacheLoader.loadAvatarImgWithGlide(context, rowData.getUser_uid(), rowData.getUserAvatarFileName()
                        , viewAvatar
                        , 25 // 圆角单位是dp
                        , R.drawable.default_avatar_yuan_50_3x, false, false);
            }


            //----------------------------------------------------------------------------- （4）无需新建listener，只需刷新关键数据到listener
            //** 确保每次item被刷新时都更新操作组件事件监听器中要记录的该item所对应的 列表的行索引号
            //** 这样就能很好地确保行索引号的正确性了
            if(showCheckBox) {
                ContentOnClickListener playListener = (ContentOnClickListener) layoutOfGotochat.getTag();
                playListener.setContentData(rowData);
            }
            else {
                HeadIconOnClickListener headListener = (HeadIconOnClickListener) layoutOfGotochat.getTag();
                headListener.setContentData(rowData);
            }
            HeadIconOnClickListener headListener = (HeadIconOnClickListener) viewAvatar.getTag();
            headListener.setContentData(rowData);

            return convertView;
        }

        /**
         * 判断当前界面模式是不是删除群员且当前行正是群主自已（本方法的作用是用于删除
         * 群成员的界面时，不要让群主把自已给删除罗！）.
         *
         * @param currentRow
         * @return true表示当前行正是群主自已且当前界面模式为删除群成员，否则不是
         */
        private boolean isGroupOwnerCanNotDeleteHimself(GroupMemberEntity currentRow)
        {
            boolean s = false;

            // 此判断表示是否是处于删除群成员的界面模式下
            if(usedForForInit == USED_FOR_VIEW_OR_MANAGER_MEMBERS && isGroupOwnerForInit)
            {
                // 且当前显示行就是群主自已，就不需要显示选择框了（难道他自已还有删除自已啊？！）
                if(isMyself(currentRow))
                    return true;
            }

            return s;
        }

        /**
         * 该行群成员是不是"我"自已。
         *
         * @param currentRow 行数据
         * @return true表示是，否则不是
         */
        private boolean isMyself(GroupMemberEntity currentRow)
        {
            boolean s = false;

            RosterElementEntity localUserInfo = MyApplication.getInstance(GroupMemberActivity.this)
                    .getIMClientManager().getLocalUserInfo();

            // 如果当前显示行就是自已
            if (localUserInfo != null
                    && currentRow != null
                    && currentRow.getUser_uid().equals(localUserInfo.getUser_uid()))
            {
                s = true;
            }

            return s;
        }

        // 本方法被Android设计为在列表数据发生变动时调用，从而及时更新UI显示
        @Override
        public void notifyDataSetChanged()
        {
            super.notifyDataSetChanged();

            if (this.getListData().size() > 0) {
                addGroupLL.setVisibility(View.GONE);
                groupListView.setVisibility(View.VISIBLE);
            }
            // 没有数据时显示显示ui
            else {
                addGroupLL.setVisibility(View.VISIBLE);
                groupListView.setVisibility(View.GONE);
            }

            // 设置确认按钮的显示
            setOkButtonForSelected(getSelectedCount());
        }

        private void deSelectedAll()
        {
            for(GroupMemberEntity gme : this.getListData())
            {
                gme.setSelected(false);
            }
        }

        /**
         * 点击item事件处理.
         */
        private class ContentOnClickListener implements View.OnClickListener {
            private GroupMemberEntity contentData = null;

            public void setContentData(GroupMemberEntity contentData) {
                this.contentData = contentData;
            }

            @Override
            public void onClick(View v) {
                if (contentData != null) {
                    if (!contentData.isEditable())
                        return;

                    // 如果当前模式是删除群员，且该行是群主自已时，就不允许响应选择状态的改变哦
                    if (!isGroupOwnerCanNotDeleteHimself(contentData)) {
                        // 支持多选
                        if (!singleSelection) {
                            contentData.setSelected(!contentData.isSelected());
                        }
                        // 支持单选
                        else {
                            // 先取消其它的选中
                            deSelectedAll();
                            // 再选中当前
                            contentData.setSelected(true);
                        }

                        // 并通知刷新列表ui
                        notifyDataSetChanged();
                    }
                }
            }
        }

        /**
         * 用户头像点击事件监听器.
         */
        private class HeadIconOnClickListener implements View.OnClickListener {
            private GroupMemberEntity contentData = null;

            public void setContentData(GroupMemberEntity contentData) {
                this.contentData = contentData;
            }

            @Override
            public void onClick(View v) {
                if (contentData != null && contentData.getUser_uid() != null)
//                  new QueryFriendInfo((Activity)context).execute(false, null, contentData.getUser_uid());
                    QueryFriendInfo.gotoWatchUserInfo(self(), contentData.getUser_uid(), null);
            }
        }
    }

    /**
     * 提交创建群请求到服务端的异步多线程封装类.
     */
    private class SubmitCreateGroupAsyncTask extends DataLoadingAsyncTask<String, Integer, DataFromServer>
    {
        private RosterElementEntity localUser = null;

        public SubmitCreateGroupAsyncTask()
        {
            super(GroupMemberActivity.this, $$(R.string.general_submitting));

            localUser = MyApplication.getInstance(GroupMemberActivity.this).getIMClientManager().getLocalUserInfo();
        }

        /**
         * 在后台执行建群信息的提交和处理结果的读取 .
         *
         * @param parems 外界传进来的参数
         * @return 查询结果，将传递给onPostExecute(..)方法
         */
        @Override
        protected DataFromServer doInBackground(String... parems)
        {
            // 提交请求到服务端
            return HttpRestHelper.submitCreateGroupToServer(
                    localUser.getUser_uid()
                    , GroupsProvider.getMyNickNameInGroupEx(context, gidForInit)
                    , constructMembersForCreateGroup(true));
        }

        /**
         * 处理服务端返回的登陆结果信息.
         */
        protected void onPostExecuteImpl(Object jsonOfResult)
        {
            Object retVal = jsonOfResult;
            if (retVal != null)
            {
                GroupEntity newGroup = HttpRestHelper.parseCreateGroupFromServer((String)jsonOfResult);

                // 建群失败
                if(newGroup == null)
                {
                    new AlertDialog.Builder(GroupMemberActivity.this)
                            .setTitle(R.string.general_error)
                            .setMessage("建群失败，请稍后再试！")
                            .setPositiveButton(R.string.general_ok,   null)
                            .setNegativeButton(R.string.general_cancel, null).show();
                    return; // 失败了，直接return
                }
                // 建群成功
                else
                {
                    // 新群聊基本信息对象放入本地群聊列表缓存中
                    MyApplication.getInstance(GroupMemberActivity.this).getIMClientManager().getGroupsProvider().putGroup(newGroup);

                    WidgetUtils.showToast(GroupMemberActivity.this, "建群成功了！", WidgetUtils.ToastType.OK);

                    // 往聊天界面中显示一条被"我"邀请入群成功的系统通知给"自已"看（此通知并非服务器发出，而是本地准备好的，仅用UI显示）
                    GChatDataHelper.addSystenInfo_inviteMembersSucessForLocalUser(GroupMemberActivity.this
                            , constructMembersForCreateGroup(false), newGroup.getG_id(), newGroup.getG_name());
                    // 进入刚建好的这个群聊聊天界面
                    startActivity(IntentFactory.createGroupChatIntent(GroupMemberActivity.this, newGroup.getG_id(), newGroup.getG_name()));

//                    registerData.setUser_uid(uid);
//                    Intent intent = IntentFactory.createRegisterSuccessIntent(RegisterActivity.this, registerData);
//                    startActivityForResult(intent, LoginActivity.REQUEST_CODE_FOR_REGISTER);

                    // 通知前一个activity（即群聊列表），及时刷新列表以便显示刚建的群
                    setResult(Activity.RESULT_OK);
                    GroupMemberActivity.this.finish();

                    return; // 成功了，直接return
                }

            }
        }

        /**
         * 构建要提交到服务端的建群群成员合（已将"自已"加入到集合中）。
         *
         * @param containMyself 是否把我自已也加入（把自已加入是用于建群时，因为群成员是包括我自已的呀）
         * @return
         */
        private ArrayList<GroupMemberEntity> constructMembersForCreateGroup(boolean containMyself)
        {
            ArrayList<GroupMemberEntity> members = getSelectedItems();

            if(containMyself)
            {
                if (localUser != null)
                {
                    // 创建群时，群成员要加上"我自已"啊
                    if (members.size() > 0)
                    {
                        GroupMemberEntity myself = new GroupMemberEntity();
                        myself.setNickname(GroupsProvider.getMyNickNameInGroupEx(context, gidForInit));//localUser.getNickname());
                        myself.setUser_uid(localUser.getUser_uid());
                        myself.setUserAvatarFileName(localUser.getUserAvatarFileName());

                        members.add(myself);
                    }
                }
            }

            return members;
        }
    }


    /**
     * 提交删除群员、邀请入群、转让群等操作请求和处理的异步执行线程实现类.
     */
    protected class OperationsAsyncTask extends DataLoadingAsyncTask<Object, Integer, DataFromServer>
    {
        private int sysActionConst = 0;
        private Object[] params = null;

        private RosterElementEntity localUser = null;

        public OperationsAsyncTask()
        {
            super(GroupMemberActivity.this, $$(R.string.general_submitting));

            localUser = MyApplication.getInstance(GroupMemberActivity.this).getIMClientManager().getLocalUserInfo();
        }

        /**
         * 在后台执行信息的提交和处于结果的读取 .
         *
         * @param params 外界传进来的参数
         * @return 查询结果，将传递给onPostExecute(..)方法
         */
        @Override
        protected DataFromServer doInBackground(Object... params)
        {
            this.params = params;
            this.sysActionConst = (Integer)params[0];

            if(sysActionConst == USED_FOR_VIEW_OR_MANAGER_MEMBERS)// 如果是群主进入到查看群成员界面，则是可以删除群员的
            {
                if(localUser != null) {
                    return HttpRestHelper.submitDeleteOrQuitGroupToServer(localUser.getUser_uid()
                            , GroupsProvider.getMyNickNameInGroupEx(context, gidForInit)
                            , gidForInit
                            , (ArrayList<ArrayList>) params[1]);
                }
            }
            else if(sysActionConst == USED_FOR_INVITE_MEMBERS)
            {
                if(localUser != null)
                    return HttpRestHelper.submitInviteToGroupToServer("0", localUser.getUser_uid()
                            , GroupsProvider.getMyNickNameInGroupEx(context, gidForInit)
                            , gidForInit
                            , (ArrayList<ArrayList>)params[1]);
            }
            else if(sysActionConst == USED_FOR_TRANSFER)
            {
                GroupMemberEntity gme = getSingleSelectedUser();
                // 该群信息
                GroupEntity ge = MyApplication.getInstance(context).getIMClientManager().getGroupsProvider().getGroupInfoByGid(gidForInit);
                Log.i(TAG, "【转让群主-DEBUG-A】gme="+gme+", ge="+ge+", GroupsProvider.sie="+MyApplication.getInstance(context).getIMClientManager().getGroupsProvider().size());
                if(gme != null && ge != null)
                {
                    Log.e(TAG, "【转让群主-DEBUG-B】HTTP请求已经提交了！！！");

                    return HttpRestHelper.submitTransferGroupToServer(
                            localUser.getUser_uid()
                            , gme.getUser_uid()
                            , GroupsProvider.getNickNameInGroup(gme.getNickname(), gme.getNickname_ingroup())
                            , gidForInit
                    );
                }
            }

            DataFromServer dfs = new DataFromServer();
            dfs.setSuccess(false);
            return dfs;
        }

        /**
         * 处理服务端返回的登陆结果信息（具体返回结果，请以 doInBackground 中调用的http接口为准）.
         */
        protected void onPostExecuteImpl(Object result)
        {
            String res;
            boolean updateSucess = "1".equals((String)result);

            if(updateSucess)
                res = $$(R.string.user_info_update_success);
            else
                res = $$(R.string.general_faild);

            Log.e(TAG, "【转让群主-DEBUG-C】进onPostExecuteImpl里了，updateSucess="+updateSucess+"， result="+result);

            // 只在服务端已更新成功时才刷新客户端数据显示
            if(updateSucess)
            {
                // 删除群成员
                if (sysActionConst == USED_FOR_VIEW_OR_MANAGER_MEMBERS)
                {
                    ArrayList<GroupMemberEntity> beRemovedMembers = getSelectedItems();

                    // 删除群成员后更新群信息里的群成员数，并通过Activity的result回调机制通知前一个Activity
                    updateCurrentGroupMemberGroupAfterSubmit(GroupMemberActivity.this, gidForInit, - beRemovedMembers.size());

                    GroupEntity ge = MyApplication.getInstance(GroupMemberActivity.this).getIMClientManager().getGroupsProvider().getGroupInfoByGid(gidForInit);
                    if(ge != null)
                    {
                        // 往聊天界面中显示一条被"我"(我就是群主自已了，不然哪有移除权限)删除群员成功
                        // 的系统通知给"自已"看（此通知并非服务器发出，而是本地准备好的，仅用UI显示）
                        GChatDataHelper.addSystenInfo_removeMembersSucessForLocalUser(GroupMemberActivity.this, beRemovedMembers, gidForInit, ge.getG_name());

//                        // 发送广播：重置群组头像缓存(用于保证本地影响群头像生成的操作，能在其它UI界面中及时将群头像刷新为最新，因为删除群员
//                        //         、邀请群员等操作会在服务端重新生成群头像，此广播就是以低耦合的方式实现本地聊头像UI刷新的通知，仅此而已)
//                        BroadcastToolKits.resetGroupAvatarCache_SEND(GroupMemberActivity.this, gidForInit);

                        // 刷新群头像的更新时间戳，关于群头像的缓存更新逻辑，请见 GroupsProvider.refreshGroupImageUpdateTimestamp(..)方法的说明
                        MyApplication.getInstance(context).getIMClientManager().getGroupsProvider().refreshGroupImageUpdateTimestamp(ge);
                    }
                }
                // 转让群主
                else if(sysActionConst == USED_FOR_TRANSFER)
                {
                    GroupMemberEntity transferTo = getSingleSelectedUser();

                    Log.e(TAG, "【转让群主-DEBUG-D】transferTo="+transferTo);

                    // 转让成功后，更新本地群列表缓存中群基本信息的群主数据
                    if(transferTo != null)
                    {
                        GroupEntity ge = MyApplication.getInstance(GroupMemberActivity.this).getIMClientManager().getGroupsProvider().getGroupInfoByGid(gidForInit);

                        Log.e(TAG, "【转让群主-DEBUG-E】ge="+ge);

                        if(ge != null)
                        {
                            // 更新新群主uid
                            ge.setG_owner_user_uid(transferTo.getUser_uid());
                            // 更新新群主昵称
                            ge.setG_owner_name(GroupsProvider.getNickNameInGroup(
                                    transferTo.getNickname(), transferTo.getNickname_ingroup()));
                            // 重置本界面中的群主标识
                            isGroupOwnerForInit = false;

//                          res = "群主权限已成功转让给\""+ge.getG_owner_name()+"\"！";

                            // 往聊天界面中显示一条被"我"(我就是群主自已了，不然哪有转让权限)转让群主权限
                            //成功的系统通知给"自已"看（此通知并非服务器发出，而是本地准备好的，仅用UI显示）
                            GChatDataHelper.addSystenInfo_transferSucessForLocalUser(GroupMemberActivity.this, ge.getG_owner_name(), gidForInit, ge.getG_name());

                            //** 设置回调数据：通知前一个activity，通知前一个界面本次群主转让完成并即时刷新界面显示
                            Intent intent=new Intent();
                            // 最新的群信息传回去
                            intent.putExtra("__updatedGroupInfo__", ge);
                            setResult(Activity.RESULT_OK, intent);
                            activityFinish();

                            Log.e(TAG, "【转让群主-DEBUG-F】activityFinish了！");
                        }
                    }
                }
                // 邀请入群
                else if(sysActionConst == USED_FOR_INVITE_MEMBERS)
                {
                    res = "邀请成功！";

                    // 当前被邀请者列表
                    ArrayList<GroupMemberEntity> beInvitedMembers = getSelectedItems();
                    // 邀请群成员后更新群信息里的群成员数，并通过Activity的result回调机制通知前一个Activity
                    updateCurrentGroupMemberGroupAfterSubmit(GroupMemberActivity.this, gidForInit, beInvitedMembers.size());
                    // 获取本地缓存的群基本信息
                    GroupEntity ge = MyApplication.getInstance(GroupMemberActivity.this).getIMClientManager().getGroupsProvider().getGroupInfoByGid(gidForInit);
                    if(ge != null) {
                        // 往聊天界面中显示一条被"我"邀请入群成功的系统通知给"自已"看（此通知并非服务器发出，而是本地准备好的，仅用UI显示）
                        GChatDataHelper.addSystenInfo_inviteMembersSucessForLocalUser(GroupMemberActivity.this, beInvitedMembers, gidForInit, ge.getG_name());
                        // 刷新群头像的更新时间戳，关于群头像的缓存更新逻辑，请见 GroupsProvider.refreshGroupImageUpdateTimestamp(..)方法的说明
                        MyApplication.getInstance(context).getIMClientManager().getGroupsProvider().refreshGroupImageUpdateTimestamp(ge);
                    }
                }
            }
            // 服务端返回失败结果
            else
            {
                if (sysActionConst == USED_FOR_TRANSFER)
                {
                    if ("2".equals((String) result))
                        res = "您已不是群主，本次转让失败！";
                    else if ("3".equals((String)result))
                    {
                        GroupMemberEntity transferTo = getSingleSelectedUser();
                        if(transferTo != null) {
                            res = GroupsProvider.getNickNameInGroup(transferTo.getNickname(), transferTo.getNickname_ingroup())+"不在群内，本次转让失败！";
                        }
                    }
                }
            }

            if (updateSucess) {
                WidgetUtils.showToast(GroupMemberActivity.this, res, WidgetUtils.ToastType.OK);
                // 并退出当前界面
                activityFinish();
            } else {
                WidgetUtils.showToast(GroupMemberActivity.this, res, WidgetUtils.ToastType.WARN);
            }
        }

        private void activityFinish()
        {
            GroupMemberActivity.this.finish();
        }
    }

    /**
     * 本方法用于删除群成员、邀请群成员后更新群信息里的群成员数，并通过Activity的result回调机制通知前一个Activity.
     *
     * @param gid 更新的群
     * @param deltaCount 变动的数据，正数表示加入了群员、负数表示删除了群员
     */
    public static void updateCurrentGroupMemberGroupAfterSubmit(Activity ac, String gid, int deltaCount)
    {
        GroupEntity ge = MyApplication.getInstance2().getIMClientManager().getGroupsProvider().getGroupInfoByGid(gid);
        if(ge != null)
        {
            // 该群删除成员前的总成员数
            int currentMemberCount = CommonUtils.getIntValue(ge.getG_member_count(), 1);
            // 新的总数
            int newCount = currentMemberCount + deltaCount;

            // 更新本地缓存里现在群的总人数
            String currentGroupMemberCount = ("" + (newCount < 1 ? "1" : newCount));
            ge.setG_member_count(currentGroupMemberCount);

            //** 设置回调数据：通知前一个activity，及时刷新最新的群成员总数
            Intent intent=new Intent();
            intent.putExtra("__currentGroupMemberCount__", currentGroupMemberCount);
            ac.setResult(Activity.RESULT_OK, intent);
        }
    }
}
